﻿using System.Collections.Generic;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;


public class DynamicObstacleManager : MonoBehaviour
{
    public static DynamicObstacleManager Instance;
    
    public FlowFieldPathfinding flowField;
    private HashSet<int2> dynamicObstacles = new HashSet<int2>();
    private Dictionary<DynamicObstacle, List<int2>> obstacleGridPositions = new Dictionary<DynamicObstacle, List<int2>>();
    private Native2DArray<bool> dynamicObstaclesNative;
    
    private void Awake()
    {
        if (Instance != null)
        {
            Destroy(Instance.gameObject);
        }
        
        Instance = this;
        Initialize();
    }

    public void Initialize()
    {
        // 初始化原生数组
        dynamicObstaclesNative = new Native2DArray<bool>(
            flowField.gridWidth,
            flowField.gridHeight,
            Allocator.Persistent
        );
    }

    public void RegisterObstacle(DynamicObstacle obstacle)
    {
        Vector3 position = obstacle.transform.position;
        float radius = obstacle.Radius;
        
        var center = flowField.WorldToGridPosition(position);
        int gridRadius = Mathf.CeilToInt(radius / flowField.CellSize);
        
        var affectedCells = new List<int2>();
        
        for (int x = -gridRadius; x <= gridRadius; x++)
        {
            for (int y = -gridRadius; y <= gridRadius; y++)
            {
                var gridPos = new int2(center.x + x, center.y + y);
                if (flowField.IsPositionValid(gridPos))
                {
                    // 确保不会重复添加
                    if (dynamicObstacles.Add(gridPos))
                    {
                        affectedCells.Add(gridPos);
                    }
                }
            }
        }
        
        Debug.Log(gameObject.GetInstanceID()  + "  " + obstacle.name + "   " + obstacleGridPositions.Count);

        obstacleGridPositions[obstacle] = affectedCells;
        flowField.MarkCellsDirty(center, gridRadius);
    }

    public void UnregisterObstacle(DynamicObstacle obstacle)
    {
        if (obstacleGridPositions.ContainsKey(obstacle))
        {
            var center = flowField.WorldToGridPosition(obstacle.transform.position);
            int gridRadius = Mathf.CeilToInt(obstacle.Radius / flowField.CellSize);
            
            foreach (var gridPos in obstacleGridPositions[obstacle])
            {
                dynamicObstacles.Remove(gridPos);
            }
            
            obstacleGridPositions.Remove(obstacle);
            flowField.MarkCellsDirty(center, gridRadius);
        }
    }

    public void UpdateObstaclePosition(DynamicObstacle obstacle, Vector3 oldPosition)
    {
        // 确保障碍物已注册
        if (!obstacleGridPositions.ContainsKey(obstacle))
        {
            RegisterObstacle(obstacle);
            return;
        }
        
        // 计算旧位置和新位置的网格中心
        var oldCenter = flowField.WorldToGridPosition(oldPosition);
        var newCenter = flowField.WorldToGridPosition(obstacle.transform.position);
        
        // 如果网格位置没有变化，不需要更新
        if (math.all(oldCenter == newCenter))
        {
            return;
        }
        
        // 移除旧位置的障碍物
        if (obstacleGridPositions.TryGetValue(obstacle, out var oldAffectedCells))
        {
            foreach (var gridPos in oldAffectedCells)
            {
                dynamicObstacles.Remove(gridPos);
            }
            
            // 标记旧位置为脏
            int oldGridRadius = Mathf.CeilToInt(obstacle.Radius / flowField.CellSize);
            flowField.MarkCellsDirty(oldCenter, oldGridRadius);
        }
        
        // 添加新位置的障碍物
        float radius = obstacle.Radius;
        int newGridRadius = Mathf.CeilToInt(radius / flowField.CellSize);
        
        var newAffectedCells = new List<int2>();
        
        for (int x = -newGridRadius; x <= newGridRadius; x++)
        {
            for (int y = -newGridRadius; y <= newGridRadius; y++)
            {
                var gridPos = new int2(newCenter.x + x, newCenter.y + y);
                if (flowField.IsPositionValid(gridPos))
                {
                    // 确保不会重复添加
                    if (dynamicObstacles.Add(gridPos))
                    {
                        newAffectedCells.Add(gridPos);
                    }
                }
            }
        }
        
        obstacleGridPositions[obstacle] = newAffectedCells;
        flowField.MarkCellsDirty(newCenter, newGridRadius);
    }

    public bool IsDynamicObstacle(int2 gridPos)
    {
        return dynamicObstacles.Contains(gridPos);
    }
    
    public Native2DArray<bool> GetDynamicObstaclesNative()
    {
        // 更新原生数组
        for (int y = 0; y < flowField.gridHeight; y++)
        {
            for (int x = 0; x < flowField.gridWidth; x++)
            {
                var gridPos = new int2(x, y);
                dynamicObstaclesNative[x,y] = dynamicObstacles.Contains(gridPos);
            }
        }
        
        return dynamicObstaclesNative;
    }
    
    private void OnDestroy()
    {
        dynamicObstaclesNative.Dispose();
    }
}